use std::error::Error;
use std::fs::File;
use std::io::{self, Read};
use std::env;

// ZIP文件的文件头长度
const ZIP_HEADER_SIZE: usize = 3000;
fn main() -> Result<(), Box<dyn Error>> {
    // 获取命令行参数
    let args: Vec<String> = env::args().collect();

    // 检查是否提供了至少一个参数（即文件名）
    if args.len() < 2 {
        eprintln!("Usage: program_name file_name");
        std::process::exit(1);
    }

    // 获取第一个参数（即文件名）
    let file_path = &args[1];
    // 替换为你的 ZIP 文件路径
    //let file_path = "D:\\book\\math\\PDF电子版\\电子版pdf.zip";

    // 打开ZIP文件
    let mut xfile = File::open(file_path.clone())?;

    // 读取文件头
    let mut header = [0; ZIP_HEADER_SIZE];
    xfile.read_exact(&mut header)?;

    // BYTE 6~7 加密标记
    // 获取加密标志位
    let flags = u16::from_le_bytes([header[6], header[7]]);
    if flags & (1 << 0) != 0 {
        println!(" encryption is used.");
        let mut legacy = true;
        // https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
        let version = header[4];
        if version == 20 {
            println!(" traditional PKWARE is used.");
        } else if version == 50 {
            legacy = false;
            println!("DES/3DES/RC2/RC4 is used.");
        } else if version == 51 {
            legacy = false;
            println!("AES/corrected RC2 encrytion.");
        } else if version == 52 {
            legacy = false;
            println!("corrected RC2-64 encrytion.");
        } else if version == 61 {
            legacy = false;
            println!("non-OAEP encryption.");
        } else if version == 62 {
            println!("central directory encryption.");
        } else if version == 63 {
            legacy = false;
            println!("blowfish/twofish encryption.");
        } else {
            println!("encryption unknown , maybe traditional or expanded version 0x{:x}. ", version);
        }
        let filenamelength = u16::from_le_bytes([header[26], header[27]]);
        let extrafieldlen = u16::from_le_bytes([header[28], header[29]]);
        println!("filenamelen:{}, extrafieldlen: {}", filenamelength, extrafieldlen);
        let tot = (filenamelength + extrafieldlen + 30 ) as usize;

        if legacy && tot < ZIP_HEADER_SIZE  {
            //not need to reread the txt
            // rust写一段代码，header id 2字节，data size 2字节，后面是数据，接着又是header id, data size, data，
            // 直到所有长度达到extrafieldlen

            let mut remaining_length = extrafieldlen as usize;
            let mut pos: usize = 30 + filenamelength as usize;
            
            while remaining_length > 0 {

                let header_id = u16::from_le_bytes([header[pos], header[pos + 1]]);
                println!("header id :{:x}", header_id);
                if header_id == 0x9901 {
                    legacy = false;
                    println!("  AE-x encryption structure");
                    //winzip
                    let integer_mode = header[pos + 8];
                    // 1: 128bit encryt. key
                    // 2  192
                    // 3  256                    
                    println!("  integer mode :{}", integer_mode);
                    if 3 == integer_mode {
                        println!("  256-bit encryption key");
                    }
                }else if header_id == 0x7075 {
                    println!("  Info-ZIP Unicode Path Extra Field");
                    println!("  Stores the UTF-8 version of the file name field");
                }
                let data_size = u16::from_le_bytes([header[pos + 2], header[pos + 3]]);
        
                if data_size as usize > remaining_length {
                    //what's wrong?
                    println!("data size too big.");
                }
                pos += data_size as usize + 4;
                remaining_length -= data_size as usize + 4; // Subtract data size and header size (2 bytes ID + 2 bytes size)
            }
        
            if remaining_length != 0 {
                // something must gowrong
                println!("remaining lenth too big.");
            }
        }else {
            //reread the text
        }
        if legacy {
            println!("bkcrack can be used.");
        }else {
            println!("bkcrack can NOT be used.");
        }
    } else {
        println!("encryption is NOT used.");
    }


    Ok(())
}

// https://blog.csdn.net/qq_43278826/article/details/118436116
// zip format or apk format
